'use strict';

var cmdHelper = require('../../../../helper/CmdHelper');

var domQuery = require('min-dom').query,
    domify = require('min-dom').domify,
    domAttr = require('min-dom').attr;

var forEach = require('lodash/forEach'),
    find = require('lodash/find');

var elementHelper = require('../../../../helper/ElementHelper');
var utils = require('../../../../Utils'),
    escapeHTML = utils.escapeHTML;

var selector = 'select[name=selectedElement]';

/**
 * Get select box containing all elements.
 *
 * @param {DOMElement} node
 *
 * @return {DOMElement} the select box
 */
function getSelectBox(node) {
    return domQuery(selector, node.parentElement);
}

/**
 * Find element by given id.
 *
 * @param {ModdleElement} eventDefinition
 *
 * @return {ModdleElement} an element
 */
function findElementById(eventDefinition, type, id) {
    var elements = utils.findRootElementsByType(eventDefinition, type);
    return find(elements, function (element) {
        return element.id === id;
    });
}

/**
 * Create an entry to modify the reference to an element from an
 * event definition.
 *
 * @param  {djs.model.Base} element
 * @param  {ModdleElement} definition
 * @param  {BpmnFactory} bpmnFactory
 * @param  {Object} options
 * @param  {string} options.label the label of the entry
 * @param  {string} options.description the description of the entry
 * @param  {string} options.elementName the name of the element
 * @param  {string} options.elementType the type of the element
 * @param  {string} options.referenceProperty the name of referencing property
 * @param  {string} options.newElementIdPrefix the prefix of a new created element
 *
 * @return {Array<Object>} return an array containing the entries
 */
module.exports = function (element, definition, bpmnFactory, options) {

    var elementName = options.elementName || '',
        elementType = options.elementType,
        referenceProperty = options.referenceProperty;

    var newElementIdPrefix = options.newElementIdPrefix || 'elem_';

    var label = options.label || '',
        description = options.description || '';

    var entries = [];

    entries.push({

        id: 'event-definitions-' + elementName,
        description: description,
        html: '<div class="bpp-row bpp-select">' +
            '<label for="camunda-' + escapeHTML(elementName) + '">' + escapeHTML(label) + '</label>' +
            '<div class="bpp-field-wrapper">' +
            '<select id="camunda-' + escapeHTML(elementName) + '" name="selectedElement" data-value>' +
            '</select>' +
            '<button class="add" id="addElement" data-action="addElement"><span>+</span></button>' +
            '</div>' +
            '</div>',

        get: function (element, entryNode) {
            utils.updateOptionsDropDown(selector, definition, elementType, entryNode);
            var reference = definition.get(referenceProperty);
            return {
                selectedElement: (reference && reference.id) || ''
            };
        },

        set: function (element, values) {
            var selection = values.selectedElement;

            var props = {};

            if (!selection || typeof selection === 'undefined') {
                // remove reference to element
                props[referenceProperty] = undefined;
                return cmdHelper.updateBusinessObject(element, definition, props);
            }

            var commands = [];

            var selectedElement = findElementById(definition, elementType, selection);
            if (!selectedElement) {
                var root = utils.getRoot(definition);

                // create a new element
                selectedElement = elementHelper.createElement(elementType, {name: selection}, root, bpmnFactory);
                commands.push(cmdHelper.addAndRemoveElementsFromList(element, root, 'rootElements', null, [selectedElement]));
            }

            // update reference to element
            props[referenceProperty] = selectedElement;
            commands.push(cmdHelper.updateBusinessObject(element, definition, props));

            return commands;
        },

        addElement: function (element, inputNode) {
            // note: this generated id will be used as name
            // of the element and not as id
            var id = utils.nextId(newElementIdPrefix);

            var optionTemplate = domify('<option value="' + escapeHTML(id) + '"> (id=' + escapeHTML(id) + ')' + '</option>');

            // add new option
            var selectBox = getSelectBox(inputNode);
            selectBox.insertBefore(optionTemplate, selectBox.firstChild);

            // select new element in the select box
            forEach(selectBox, function (option) {
                if (option.value === id) {
                    domAttr(option, 'selected', 'selected');
                } else {
                    domAttr(option, 'selected', null);
                }
            });

            return true;
        }

    });

    return entries;

};
